﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.IO;
using System.Threading;
using System.Windows.Threading;
using System.Data;
using System.Collections;
using System.Diagnostics;
using System.Windows.Media.Animation;
using DatabaseEntegreItri.Utils;

namespace DatabaseEntegreItri
{
    enum ThreadState{
        PROGRESS,
        PAUSED,
        OFFLINE
    }
    
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        LocumUpdate locumUpdate = null;

        //ThreadState stateThread = ThreadState.OFFLINE;

        const int ANIM_SHOW = 1;
        const int ANIM_HIDE = 2;
        const int ANIM_CLOSE = 3;

        FileWatcher watherItri = null;
        FileWatcher watherLocum = null;

        Dispatcher uiDispatcher = null;
        int animationMilis = 500;
        bool isAppClosing = false;

        bool threadCompleted = true;

        bool threadInProgres = false;
        public bool ThreadInProgress
        {
            get { return threadInProgres; }
            set {
                invokeAction(delegate()
                    {
                if (value)
                {
                    this.Cursor = Cursors.Wait;
                    //Mouse.OverrideCursor = Cursors.Wait;
                }
                else {
                    this.Cursor = Cursors.Arrow;
                    //Mouse.OverrideCursor = Cursors.Arrow ;
                }
                });
                threadInProgres = value; 
            }
        }
        bool isAnimatingNow = false;
        bool shouldAnimate = false;

        String errorCheckFiles = "Dosyaları Kontrol Edin !!!";
        String DBLocumFilePath = "";
        String DBItriFilePath = "";
        
        #region Interface and Events

        double lastWinPositionX = 0;
        double lastWinPositionY = 0;

        double winLastXPosition = double.MaxValue;
        double winLastYPosition = double.MaxValue;

        public Window1()
        {
            InitializeComponent();
            this.Width = 440;
            uiDispatcher = this.Dispatcher;
            this.Left = WinDefaultXPos;
            this.Top = WinDefaultYPos;
            hataGrid.Margin = new Thickness(0, 0, 0, 0);
            shouldAnimate = GlobalAccess.varSystem.IsInDebugMode;
        }

        private void btnMinimize_Click(object sender, RoutedEventArgs e)
        {
            EventHandler handler = (s, x) => { hideMethod(); };
            animationCreate(ANIM_HIDE, handler);
        }

        private void win_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Normal)
            {
                animationCreate(ANIM_SHOW, null);
            }
        }

        private void buttonPause_Click(object sender, RoutedEventArgs e)
        {
            Button butonSender = sender as Button;
            if (butonSender.Tag.Equals("NORMAL"))
            {
                if (locumUpdate != null)
                {
                    locumUpdate.pauseOperations(true);
                }
                butonSender.Tag = "PAUSED";
                butonSender.Content = "Devam Et";
            }
            else
            {
                if (locumUpdate != null)
                {
                    locumUpdate.pauseOperations(false);
                    ThreadInProgress = true;
                }
                butonSender.Tag = "NORMAL";
                butonSender.Content = "Ara Ver";
            }
        }

        private void buttonStop_Click(object sender, RoutedEventArgs e)
        {            
            if (locumUpdate != null)
            {
                locumUpdate.stopOperations(true);
            }
            labelInfo.Content = "Stopping !!!";            
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (!threadCompleted && !isAppClosing)
            {
                QuestionDialog qDialog = new QuestionDialog(this);
                qDialog.ShowDialog();

                bool res = (bool)qDialog.DialogResult;
                if (!res)
                {
                    e.Cancel = true;
                }
                else
                {
                    EventHandler handlerSample = (s, x) => { shutDownMethod(); };
                    e.Cancel = true;
                    animationCreate(ANIM_CLOSE, handlerSample);
                }
            }
            else
            {
                EventHandler handlerSample = (s, x) => { shutDownMethod(); };
                e.Cancel = true;
                animationCreate(ANIM_CLOSE, handlerSample);
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    this.DragMove();
                }
            }
            catch (Exception) {}
        }

        private void win_Loaded(object sender, RoutedEventArgs e)
        {            
            animationCreate(ANIM_SHOW, null);
        }

        private void hideMethod()
        {
            this.WindowState = WindowState.Minimized;
        }

        private void shutDownMethod()
        {
            isAppClosing = true;
            Application.Current.Shutdown();
        }

        public double WinDefaultXPos
        {
            get
            {
                return System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2 - (Width / 2);
            }
        }
        public double WinDefaultYPos
        {
            get { return System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height / 2 - (Height / 2); }
        }

        #region Animation
        
        private DoubleAnimation getDoubleAnim(DependencyProperty dp, String controlName, Duration duration)
        {
            double acc = 1;
            DoubleAnimation animScaleX = new DoubleAnimation();
            animScaleX.Duration = duration;
            animScaleX.AccelerationRatio = acc;
            animScaleX.DecelerationRatio = 1 - acc;
            Storyboard.SetTargetProperty(animScaleX, new PropertyPath(dp));
            Storyboard.SetTargetName(animScaleX, controlName);
            return animScaleX;
        }

        private void animationCreate(int ANIM_TYPE, EventHandler handler)
        {
            if (!shouldAnimate)
            {
                if (handler != null) handler.Invoke(null, null);
                return;
            }
            if (isAnimatingNow) return;
            double hiddenXPosition = 0;
            double hiddenYPosition = 0;
            try
            {
                Taskbar taskbar = new Taskbar();

                hiddenXPosition = taskbar.Bounds.Left;
                hiddenYPosition = taskbar.Bounds.Top;

                if (winLastXPosition == double.MaxValue)
                {
                    winLastXPosition = WinDefaultXPos;
                    winLastYPosition = WinDefaultYPos;
                }
                else
                {
                    winLastXPosition = lastWinPositionX;
                    winLastYPosition = lastWinPositionY;
                }
                if (ANIM_TYPE == ANIM_HIDE)
                {
                    lastWinPositionX = this.Left;
                    lastWinPositionY = this.Top;
                }
            }
            catch (Exception) { }

            string controlName = "control1";
            this.RegisterName(controlName, this);

            int milis = animationMilis;

            Duration duration = new Duration(TimeSpan.FromMilliseconds(milis));

            Storyboard story = new Storyboard();

            DoubleAnimation animScaleX = getDoubleAnim(Window1.ScaleXProperty, controlName, duration);
            DoubleAnimation animScaleY = getDoubleAnim(Window1.ScaleYProperty, controlName, duration);
            DoubleAnimation animWinPosX = getDoubleAnim(Window1.WinPosXProperty, controlName, duration);
            DoubleAnimation animWinPosY = getDoubleAnim(Window1.WinPosYProperty, controlName, duration);
            DoubleAnimation animOpacity = getDoubleAnim(Window1.OpacityWinProperty, controlName, duration);

            if (ANIM_TYPE == ANIM_SHOW)
            {
                animOpacity.From = 0;
                animOpacity.To = OPACITY_WIN_DEFAULT;
                animScaleY.From = 0;
                animScaleY.To = 1;
            }
            else
            {
                animOpacity.From = OPACITY_WIN_DEFAULT;
                animOpacity.To = 0;
                animScaleY.From = 1;
                animScaleY.To = 0;
            }
            if (ANIM_TYPE == ANIM_SHOW)
            {
                animScaleX.From = 0;
                animScaleX.To = 1;
            }
            else
            {
                animScaleX.From = 1;
                animScaleX.To = 0;
            }
            if (ANIM_TYPE == ANIM_SHOW)
            {
                animWinPosX.From = hiddenXPosition;
                animWinPosX.To = winLastXPosition;
            }
            else
            {
                animWinPosX.From = this.Left;
                animWinPosX.To = hiddenXPosition;
            }
            if (ANIM_TYPE == ANIM_SHOW)
            {
                animWinPosY.From = hiddenYPosition;
                animWinPosY.To = winLastYPosition;
            }
            else
            {
                animWinPosY.To = hiddenYPosition;
                animWinPosY.From = this.Top;
            }
            story.Children.Add(animScaleX);
            story.Children.Add(animScaleY);
            story.Children.Add(animWinPosX);
            story.Children.Add(animWinPosY);
            story.Children.Add(animOpacity);
            story.Completed += (object s, EventArgs x) =>
            {
                isAnimatingNow = false;
            };
            if (handler != null)
            {
                story.Completed += handler;                
            }

            story.Begin(this);
            isAnimatingNow = true;
        }
        
        #endregion
        
        private void setDbFileLocum(String fileName)
        {
            DBPathLocum = fileName;
            EventHandler handler = (s, x) => { DBPathLocum = (string)s; };
            if (watherLocum != null) watherLocum.stopWatcher(); watherLocum = null;
            watherLocum = new FileWatcher(DBPathLocum, handler, this.Dispatcher);            
        }
       
        private void setDbFileItri(String fileName)
        {
            DBPathItri = fileName;
            EventHandler handler = (s, x) => { DBPathItri = (string)s;};
            if (watherItri != null) watherItri.stopWatcher(); watherItri = null;
            watherItri = new FileWatcher(DBPathItri, handler, this.Dispatcher);
        }

        private void buttonSelectLocum_Click(object sender, RoutedEventArgs e)
        {
            String fileName = WindowUtils.getDBFile("LocumDb.mdf", "mdf");
            if (fileName != null)
            {
                setDbFileLocum(fileName);
            }
        }

        private void buttonSelectItri_Click(object sender, RoutedEventArgs e)
        {
            String fileName = WindowUtils.getDBFile("Urodinami.mdf", "mdf");
            if (fileName != null)
            {
                setDbFileItri(fileName);
            }
        }

        private void buttonClean_Click(object sender, RoutedEventArgs e)
        {            
            cleanCallWithUpdateClass();
        }

        private void buttonUpdate_Click(object sender, RoutedEventArgs e)
        {
            startUpdateWithLocumUpdateClass();
        }        

        private void changeButonStates(bool enabled)
        {
            invokeAction((ThreadStart)delegate()
            {
                buttonSelectLocum.IsEnabled = enabled;
                buttonSelectItri.IsEnabled = enabled;
                buttonStop.IsEnabled = !enabled;
                buttonPause.IsEnabled = !enabled;
                buttonUpdate.IsEnabled = enabled;
                buttonClean.IsEnabled = enabled;
                if (!enabled)
                {
                    labelInfo.Content = "";
                }
            });
        }

        private void updateProgressBarText(String text, bool onlyTooltip)
        {
            invokeAction((ThreadStart)delegate()
            {
                if (!onlyTooltip)
                {
                    processTextBlock.Text = text;
                }
                processTextBlock.ToolTip = text;
                progressBar1.ToolTip = text;
            });
        }

        private void updateProgressBar(int currentData, int maxDataCount, double remainingTime)
        {
            updateProgressBarText("" + (currentData+1) + ". hasta güncelleniyor", true);

            if (remainingTime < 0) return;

            invokeAction((ThreadStart)delegate()
            {
                progressBar1.Maximum = maxDataCount;
                processTextBlock.Text = currentData + "/" +
                    progressBar1.Maximum + " Kalan Zaman : " + remainingTime + " dk";
                progressBar1.Value = currentData;
            });
        }

        private void win_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F1)
            {
                Help help = new Help();
                Point a = WindowUtils.getChildLocationInRightSide(this,
                    new System.Windows.Size(help.Width, help.Height));
                help.Top = a.Y;
                help.Left = a.X;
                help.Owner = this;
                help.ShowDialog();
            }
            else if (Keyboard.IsKeyDown(Key.LeftCtrl) &&
                (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.LeftShift))
                && Keyboard.IsKeyDown(Key.F12)) {
                    new LogScreen().ShowDialog();                
            }
        }

        private void buttonStilSec_Click(object sender, RoutedEventArgs e)
        {
            SelectStyle sStyle = new SelectStyle();
            Point a = WindowUtils.getChildLocationInRightSide(this,
                    new System.Windows.Size(sStyle.Width, sStyle.Height));
            sStyle.Top = a.Y;
            sStyle.Left = a.X;
            sStyle.ShowDialog();
        }

        private String DragGetFileName(DragEventArgs e)
        {
            object text = e.Data.GetData(DataFormats.StringFormat, true);
            if (text != null)
            {
                hataText.Text = "Drag Text :\n" + text.ToString();
                hataGrid.Visibility = Visibility.Visible;

                new Thread(delegate()
                {
                    Thread.Sleep(5000);
                    invokeAction((ThreadStart)delegate()
                    {
                        hataGrid.Visibility = Visibility.Collapsed;
                    });
                }).Start();
            }

            string[] fileNames = e.Data.GetData(DataFormats.FileDrop, true) as string[];
            if (fileNames == null) return null;
            foreach (string str in fileNames)
            {
                FileInfo fInfoTemp = new FileInfo(str);
                if ((fInfoTemp.Attributes & FileAttributes.Directory) == 0)
                {
                    // This is a file
                    if (fInfoTemp.Extension.Equals(".mdf"))
                    {
                        return str;
                    }
                }
                else
                {
                    // This is a folder
                }

            }
            return null;
        }

        private void Border_Drop(object sender, DragEventArgs e)
        {
            String p = DragGetFileName(e);
            if (p != null)
                setDbFileLocum(p);
        }

        private void Border_Drop_1(object sender, DragEventArgs e)
        {
            String p = DragGetFileName(e);
            if (p != null)
                setDbFileItri(p);
        }

        #endregion

        #region Database Functions

        private void cleanCallWithUpdateClass()
        {
            changeButonStates(false);
            progressBar1.Value = 0;
            if (File.Exists(DBLocumFilePath))
            {
                LocumUpdate locumClean = new LocumUpdate(DBLocumFilePath, DBItriFilePath);
                locumClean.updateCompleted += new UpdateCompletedHandler(locumClean_updateCompleted);
                locumClean.startClean();
            }
            else
            {
                labelInfo.Content = errorCheckFiles;
            }
        }

        void locumClean_updateCompleted(string result)
        {
            if (result == "")
            {
                invokeAction((ThreadStart)delegate()
                {
                    labelInfo.Content = "Silme İşlemi Başarılı";
                });

            }
            else
            {
                invokeAction((ThreadStart)delegate()
                {
                    labelInfo.Content = "Silme Hatası";
                });
            }
            invokeAction((ThreadStart)delegate()
                    {
                        progressBar1.Value = progressBar1.Maximum;
                    });
            changeButonStates(true);
        }

        private void startUpdateWithLocumUpdateClass()
        {
            
            changeButonStates(false);
            progressBar1.Value = 0;
            if (File.Exists(DBLocumFilePath) && File.Exists(DBItriFilePath))
            {
                threadCompleted = false;
                ThreadInProgress = true;
                locumUpdate = new LocumUpdate(DBLocumFilePath, DBItriFilePath);
                locumUpdate.updateCompleted += new UpdateCompletedHandler(locumUpdate_updateCompleted);
                locumUpdate.statusUpdated += new UpdateStatusHandler(locumUpdate_statusUpdated);
                locumUpdate.progressUpdated += new UpdateProgressHandler(locumUpdate_progressUpdated);
                locumUpdate.updatePaused += new UpdatePausedHandler(locumUpdate_updatePaused);
                locumUpdate.start();
                
            }
            else
            {
                labelInfo.Content = errorCheckFiles;
                changeButonStates(true);                
            }
        }

        void locumUpdate_updatePaused()
        {
            ThreadInProgress = false;           
        }

        void locumUpdate_progressUpdated(int currentData, int maxDataCount, double remainingTime)
        {
            updateProgressBar(currentData, maxDataCount, remainingTime);
        }

        void locumUpdate_statusUpdated(string result)
        {
            updateProgressBarText(result, false);
        }

        void locumUpdate_updateCompleted(string result)
        {
            String updateText = result;
            if (updateText.Equals(""))
            {
                invokeAction((ThreadStart)delegate()
                {
                    labelInfo.Content = "Güncelleme İşlemi Başarılı";
                    progressBar1.Value = progressBar1.Maximum;
                });
            }
            else
            {
                invokeAction((ThreadStart)delegate()
                {
                    labelInfo.Content = "Hata : " + updateText;
                    processTextBlock.Text = "0/0";
                });
            }
            changeButonStates(true);
            ThreadInProgress = false;
            threadCompleted = true;
        }

        #endregion

        #region Simple Utils

        private void invokeAction(ThreadStart st)
        {
            uiDispatcher.Invoke(DispatcherPriority.DataBind, st);
        }

        #endregion

        #region Dependency Properties
        public static DependencyProperty ScaleXProperty = DependencyProperty.RegisterAttached("ScaleX", typeof(double), typeof(Window1), new PropertyMetadata(1.0));
        public double ScaleX
        {
            get { return (double)GetValue(ScaleXProperty); }
            set
            {
                SetValue(ScaleXProperty, value);
            }
        }
        public static DependencyProperty ScaleYProperty = DependencyProperty.RegisterAttached("ScaleY", typeof(double), typeof(Window1), new PropertyMetadata(1.0));
        public double ScaleY
        {
            get { return (double)GetValue(ScaleYProperty); }
            set
            {
                SetValue(ScaleYProperty, value);
            }
        }
        public static DependencyProperty WinPosXProperty = DependencyProperty.RegisterAttached("WinPosX", typeof(double), typeof(Window1), new PropertyMetadata(0.0));
        public double WinPosX
        {
            get { return (double)GetValue(WinPosXProperty); }
            set
            {
                SetValue(WinPosXProperty, value);
            }
        }
        public static DependencyProperty WinPosYProperty = DependencyProperty.RegisterAttached("WinPosY", typeof(double), typeof(Window1), new PropertyMetadata(0.0));
        public double WinPosY
        {
            get { return (double)GetValue(WinPosYProperty); }
            set
            {
                SetValue(WinPosYProperty, value);
            }
        }
        public static DependencyProperty WinRotateProperty = DependencyProperty.RegisterAttached("WinRotate", typeof(double), typeof(Window1), new PropertyMetadata(0.0));
        public double WinRotate
        {
            get { return (double)GetValue(WinRotateProperty); }
            set
            {
                SetValue(WinRotateProperty, value);
            }
        }
        public static double OPACITY_WIN_DEFAULT = 1;
        public static DependencyProperty OpacityWinProperty =
            DependencyProperty.RegisterAttached("OpacityWin", typeof(double), typeof(Window1), new PropertyMetadata(OPACITY_WIN_DEFAULT));
        public double OpacityWin
        {
            get { return (double)GetValue(OpacityWinProperty); }
            set
            {
                SetValue(OpacityWinProperty, value);
            }
        }

        public static DependencyProperty DBPathItriProperty =
            DependencyProperty.RegisterAttached("DBPathItri", typeof(String), typeof(Window1), new PropertyMetadata(null));
        public String DBPathItri
        {
            get { return (String)GetValue(DBPathItriProperty); }
            set
            {
                DBItriFilePath = value;
                SetValue(DBPathItriProperty, value);
            }
        }

        public static DependencyProperty DBPathLocumProperty =
            DependencyProperty.RegisterAttached("DBPathLocum", typeof(String), typeof(Window1), new PropertyMetadata(null));
        public String DBPathLocum
        {
            get { return (String)GetValue(DBPathLocumProperty); }
            set
            {
                DBLocumFilePath = value;
                SetValue(DBPathLocumProperty, value);
            }
        }
        #endregion
                

    }
}

